Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@enhance/ssr
Advanced tools
Server sider render for Custom Elements.
Enhance enables a web standards based workflow that embraces the platform by supporting Custom Elements and slot syntax.
npm i @enhance/ssr
import HelloWorld from './path/to/elements/hello-world.mjs'
import enhance from '@enhance/ssr'
const html = enhance({
elements: {
'hello-world': HelloWorld
}
})
console.log(html`<hello-world greeting="Well hi!"></hello-world>`)
Elements are pure functions that are passed an object containing an html
function used to expand custom elements and a state object comprised of attrs
which are the attributes set on the custom element and a store
object that contains application state.
export default function HelloWorld({ html, state }) {
const { attrs } = state
const { greeting='Hello World' } = attrs
return html`
<style scope="global">
h1 {
color: red;
}
</style>
<h1>${greeting}</h1>
`
}
The rendered output
<head>
<style scope="global">
h1 {
color: red;
}
</style>
</head>
<body>
<hello-world>
<h1>Hello World</h1>
</hello-world>
</body>
You can also use an object that exposes a render
function as your template. The render function will be passed the same arguments { html:function, state:object }
.
{
attrs: [ 'label' ],
init(el) {
el.addEventListener('click', el.click)
},
render({ html, state }) {
const { attrs={} } = state
const { label='Nope' } = attrs
return html`
<pre>
${JSON.stringify(state)}
</pre>
<button>${ label }</button>
`
},
click(e) {
console.log('CLICKED')
},
adopted() {
console.log('ADOPTED')
},
connected() {
console.log('CONNECTED')
},
disconnected() {
console.log('DISCONNECTED')
}
}
Use these options objects with the enhance custom element factory
Supply initital state to enhance and it will be passed along in a store
object nested inside the state object.
import MyStoreData from './path/to/elements/my-store-data.mjs'
import enhance from '@enhance/ssr'
const html = enhance({
elements: {
'my-store-data': MyStoreData
},
initialState: { apps: [ { users: [ { name: 'tim', id: 001 }, { name: 'kim', id: 002 } ] } ] }
})
console.log(html`<my-store-data app-index="0" user-index="1"></my-store-data>`)
export default function MyStoreData({ html, state }) {
const { attrs, store } = state
const appIndex = attrs['app-index']
const userIndex = attrs['user-index']
const { id='', name='' } = store?.apps?.[appIndex]?.users?.[userIndex] || {}
return `
<div>
<h1>${name}</h1>
<h1>${id}</h1>
</div>
`
}
The store is used to pass state to all components in the tree.
Enhance supports the use of slots
in your custom element templates.
export default function MyParagraph({ html }) {
return html`
<p>
<slot name="my-text">
My default text
</slot>
</p>
`
}
You can override the default text by adding a slot attribute with a value that matches the slot name you want to replace.
<my-paragraph>
<span slot="my-text">Let's have some different text!</span>
</my-paragraph>
Enhance supports unnamed slots for when you want to create a container element for all non-slotted child nodes.
⚠️ per the spec default content is not supported in slots
export default function MyParagraph({ html }) {
return html`
<p>
<slot>This will not render.</slot>
</p>
`
}
<my-paragraph>
This will render <strong>all</strong> authored children.
</my-paragraph>
Enhance supports the inclusion of script and style transform functions. You add a function to the array of scriptTransforms
and/or styleTransforms
and are able to transform the contents however you wish, just return your desired output.
import enhance from '@enhance/ssr'
const html = enhance({
elements: {
'my-transform-script': MyTransformScript
},
scriptTransforms: [
function({ attrs, raw }) {
// raw is the raw text from inside the script tag
// attrs are the attributes from the script tag
return raw + ' yolo'
}
],
styleTransforms: [
function({ attrs, raw }) {
// raw is the raw text from inside the style tag
// attrs are the attributes from the style tag
const { scope } = attrs
return `
/* Scope: ${ scope } */
${ raw }
`
}
]
})
function MyTransformScript({ html }) {
return html`
<style scope="component">
:host {
display: block;
}
</style>
<h1>My Transform Script</h1>
<script type=module>
class MyTransformScript extends HTMLElement {
constructor() {
super()
}
}
customElements.define('my-transform-script', MyTransformScript)
</script>
`
}
console.log(html`<my-transform-script></my-transform-script>`)
bodyContent
Enhance SSR outputs an entire valid HTML page but you can pass bodyContent: true
to get the content of the body element. This can be useful for when you want to isolate output HTML to only the Custom Element you are authoring.
const html = enhance({
bodyContent: true,
elements: {
'my-paragraph': MyParagraph,
}
})
const output = html`
<my-paragraph></my-paragraph>
`
context
There are times you will need to pass state to nested child custom elements. To avoid the tedium of passing attributes through multiple levels of nested elements Enhance SSR supplies a context
object to add state to.
Parent sets context
export default function MyContextParent({ html, state }) {
const { attrs, context } = state
const { message } = attrs
context.message = message
return html`
<slot></slot>
`
}
Child retrieves state from parent supplied context
export default function MyContextChild({ html, state }) {
const { context } = state
const { message } = context
return html`
<span>${ message }</span>
`
}
Authoring
<my-context-parent message="hmmm">
<div>
<span>
<my-context-child></my-context-child>
</span>
</div>
</my-context-parent>
instanceID
When rendering custom elements from a single template there are times where you may need to target a specific instance. The instanceID
is passed in the state
object.
export default function MyInstanceID({ html, state }) {
const { instanceID='' } = state
return html`
<p>${instanceID}</p>
`
}
P.S. Enhance works really well with Begin.
FAQs
Server-side rendering for custom elements with template and slots support
The npm package @enhance/ssr receives a total of 55 weekly downloads. As such, @enhance/ssr popularity was classified as not popular.
We found that @enhance/ssr demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.